import re
from datetime import datetime, timedelta

from django.contrib.auth.models import update_last_login
from django.utils.timezone import make_aware
from rest_framework import serializers
from django.contrib.auth import get_user_model
from rest_framework.validators import UniqueValidator
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.settings import api_settings
from rest_framework_simplejwt.views import TokenObtainPairView

from users.models import VerifyCode

User = get_user_model()


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super(MyTokenObtainPairSerializer, cls).get_token(user)

        # Add custom claims
        token['username'] = user.username
        token['email'] = user.email
        token['mobile'] = user.mobile
        token['user_id'] = user.id
        return token

    def validate(self, attrs):
        data = super().validate(attrs)

        # 获取Token对象
        refresh = self.get_token(self.user)
        data['refresh'] = str(refresh)
        data['access'] = str(refresh.access_token)

        my_user = User.objects.filter(pk=self.user.id).first()
        if my_user:
            # use user serelizor or parse required fields
            data['user'] = UserDetailSerializer(my_user).data

        if api_settings.UPDATE_LAST_LOGIN:
            update_last_login(None, self.user)
        # 令牌到期时间
        data['expire'] = refresh.access_token.payload['exp']  # 有效期
        # 用户名
        data['username'] = self.user.username
        # 邮箱
        data['user_id'] = self.user.id
        return data


class MyObtainTokenPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer


class UserDetailSerializer(serializers.ModelSerializer):
    """
    用户详情序列化
    """
    class Meta:
        model = User
        fields = ('name', 'gender', 'birthday', 'email', 'mobile')


class SmsSerializer(serializers.Serializer):
    mobile = serializers.CharField(label='手机号', max_length=11)
    image_code_id = serializers.UUIDField(label='图形验证码id')
    image_code = serializers.CharField(label='图形验证码', max_length=4)
    sms_code = serializers.CharField(label='短信验证码', max_length=6)
    sms_code_id = serializers.UUIDField(label='短信验证码id')

    def validate_mobile(self, mobile):
        """
        验证手机号
        :param mobile:
        :return:
        """
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError('手机号格式不正确')

        if User.objects.filter(mobile=mobile).exists():
            raise serializers.ValidationError('手机号已注册')

        one_minutes_ago = datetime.now() - timedelta(days=0, hours=0, minutes=1, seconds=0)
        if VerifyCode.objects.filter(mobile=mobile, add_time__gt=one_minutes_ago).exists():
            raise serializers.ValidationError('发送短信过于频繁')
        return mobile


class UserRegSerializer(serializers.ModelSerializer):
    code = serializers.CharField(label='短信验证码',required=True, max_length=4, min_length=4, write_only=True,
                                 error_messages={
                                    'blank': '请输入验证码',
                                    'required': '请输入验证码',
                                    'min_length': '验证码长度不正确',
                                    'max_length': '验证码长度不正确',
                                 },help_text="验证码")
    username = serializers.CharField(label='用户名', required=True, allow_blank=False, max_length=11, min_length=11,
                                     validators=[UniqueValidator(queryset=User.objects.all(), message='用户已存在')],
                                     help_text="用户名")
    password = serializers.CharField(label='密码', required=True, allow_blank=False,
                                     # max_length=20, min_length=8,
                                     style={'input_type': 'password'},
                                     write_only=True,
                                     error_messages={
                                        'blank': '请输入密码',
                                        'required': '请输入密码',
                                        'min_length': '密码长度不正确',
                                        'max_length': '密码长度不正确',
                                     }, help_text="密码")
    """
    用户注册序列化器
    """
    def validate_code(self, code):
        """
        验证短信验证码
        :param code:
        :return:
        """
        sms_code = self.context['request'].data.get('sms_code')
        mobile = self.initial_data.get('username')
        verify_records = VerifyCode.objects.filter(mobile=mobile).order_by('-add_time')
        if not verify_records:
            raise serializers.ValidationError('验证码不存在')
        if verify_records:
            last_record = verify_records[0]
            five_minutes_ago = datetime.now() - timedelta(hours=0, minutes=5,
                                                          seconds=0)
            if last_record.add_time < make_aware(five_minutes_ago):
                raise serializers.ValidationError('验证码过期')
            if last_record.code != code:
                raise serializers.ValidationError('验证码错误')
        if not mobile:
            raise serializers.ValidationError('手机号不能为空')

    # def create(self, validated_data):
    #     """
    #     创建用户
    #     :param validated_data:
    #     :return:
    #     """
    #     user = super(UserRegSerializer, self).create(validated_data=validated_data)
    #     user.set_password(validated_data['password'])
    #     user.save()
    #     return user

    def validate(self, attrs):
        """
        验证密码
        :param attrs:
        :return:
        """
        attrs["mobile"] = attrs["username"]
        del attrs['code']
        # password = attrs.get('password')
        # password2 = attrs.get('password2')
        # if password!= password2:
        #     raise serializers.ValidationError('两次密码不一致')
        return attrs

    class Meta:
        model = User
        fields = ('username', 'mobile', 'code', 'password')
       #  extra_kwargs = {
       #      'password': {
       #          'write_only': True,
       #         'min_length': 8,
       #     }
       # }